﻿using Kinlo.Entitys;
using Kinlo.MESDocking;
using NPOI.OpenXmlFormats.Spreadsheet;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using UIWindows.GlobalStatics;
using UIWindows.Models.Devices;
using UIWindows.Tools.Helper;
using XCode;
using XingLucifer.Devices;
using XingLucifer.IBase.Enums;

namespace UIWindows.Services.PLC_MESHelper
{
    /// <summary>
    /// 预充行装盘
    /// </summary>
    public class RowPlateFinishedHandler : HelperBase
    {
        PLCBase InjMachine { get; set; }

        MESWinderOutRecordAddRec _mesWinderOutRecord { get; set; }
        public RowPlateFinishedHandler(
            DeviceInteractiveaddressStatic deviceInteractiveaddressStatic,
            DeviceClientModel deviceModel,
            TemporaryStatic temporaryStatic,
            ParameterStatic parameterStatic,
            DeviceConfigStatic deviceConfigStatic,
            SystemConfigStatic systemConfigStatic,
             HomeStatic homeStatic,
             Action<string, string, string, string, string, long, DateTime, string, string, string, string> log, Action<string, string, string> dialog
            ) : base(deviceInteractiveaddressStatic, deviceModel, temporaryStatic, parameterStatic, deviceConfigStatic, systemConfigStatic, homeStatic, log, dialog)
        {
            InjMachine = deviceModel.PLC;
            _mesWinderOutRecord = new MESWinderOutRecordAddRec(_log, _dialog);

            //OCV.Meta.TableName = $"OCV_{DateTime.Now:yyyy}{DateTime.Now.GetQuarterly()}";
            //Precharge.Meta.TableName = $"Precharge_{DateTime.Now:yyyy}{DateTime.Now.GetQuarterly()}";
            //Plate.Meta.TableName = $"Plate_{DateTime.Now:yyyy}{DateTime.Now.GetQuarterly()}";

        }

        int[] indexs = new int[16] { 241, 225, 209, 193, 177, 161, 145, 129, 113, 97, 81, 65, 49, 33, 17, 1 };
        object locker = new object();

        public override Task Handle()
        {
            //KL21050011Machine InjMachine = null;
            Int16 testResult = 1;
            bool HaveNG = false;

            try
            {
                OCV.Meta.TableName = $"OCV_{startTime:yyyy}{startTime.GetQuarterly()}";
                Precharge.Meta.TableName = $"Precharge_{startTime:yyyy}{startTime.GetQuarterly()}";
                Plate.Meta.TableName = $"Plate_{startTime:yyyy}{startTime.GetQuarterly()}";

                //var dicts = ctx.Container.Get<ConcurrentDictionary<string, object>>();
                //var cfg = ctx.Container.Get<CFG>();
                //InjMachine = (KL21050011Machine)dicts.GetOrAdd("InjMachine", InjMachine);
                //var Counter = ctx.Container.Get<Counter>();
                //var data = ctx.Container.Get<PlateData>();
                //var DB = ctx.Container.Get<RepoBase>();
                var values = InjMachine.Read("DM1000", 56);

                //装盘行号 DM1004
                var rowNo =values[4];

                //var barcodeBytes = InjMachine.PLC.Read("DM21360", 640);
                //$"【装盘】行{rowNo}:{string.Join(",",barcodeBytes)}".Info();
                //if (barcodeBytes.Count != 640)
                //    $"【装盘】数据读取异常".Info();
                //var trayNos = InjMachine.PlateIndexs(); 
                //18线用这个地址
                var baseAddr = 24300;
                //26线用这个地址
                //var baseAddr = 23240;
                var strCode = new List<ushort>();
                for (int i = 0; i < 4; i++)
                {
                    var val = InjMachine.Read($"DM{baseAddr}", 160);
                    strCode.AddRange(val);
                    baseAddr += 160;
                }
                var barcodes = new List<string>();
                //ProductionCounter.Tmp.Load();
                for (int i = 0; i < 16; i++)
                {
                    var bar = InjMachine.ToString(strCode.Skip(i * 40).Take(40));

                    //如果取PLC的是虚拟码，那就是屏蔽了喷码枪，则用方法重新生成不重复的虚拟码
                    if (bar.Contains("XNM"))
                    {
                        bar = GenerateUniqueBarcode();
                    }
                    _parameter.InCount++;
                    _temporaryStatic.mesCollectionItemsTemporary[(int)machineInfo_Type].InCount= _parameter.InCount;
                    //ProductionCounter.Tmp.InCount++;
                    barcodes.Add(bar);
                }
                //ProductionCounter.Tmp.Save();
                var strCCD = new List<ushort>();
                var ccddata = 14000;
                ///////////读取CCD数据////////////
                for (int i = 0; i < 16; i++)
                {
                    var val = InjMachine.Read($"ZF{ccddata}", 12);
                    for (int j = 0; j < val.Count; j++)
                    {
                        if (j % 2 == 0)
                        {
                            strCCD.Add(val[j]);
                        }
                    }
                    //strCCD.AddRange(val);
                    ccddata += 40;
                }
                int stop = 0;
                ///////////////////////
                RunLog($"【装盘】{rowNo} {string.Join(";", barcodes)}");


                //var batts = data.PlateQueueList.Take(16).ToArray();


                // $"【装盘】{rowNo} {string.Join(";",trayNos)} ".Info();
                //var trayNoContains = barcodes.Zip(batts, (f, s) => $"PC:{s.Barcode}~PLC:{f}");

                //$"【装盘】条码匹配关联:\r\n{(string.Join(";", trayNoContains))}".Info();


                var barcode = new List<string>();
                var datetime = DateTime.Now;
                var plateList1 = new List<Plate>();
                var deleteBatt = new List<PlateBattery>();
                var removeBarcodes = new List<string>();

       

                for (int i = 0, c = 16; i < 16; i++)
                {
                    var bar = barcodes[i];
                    var plate = new Plate
                    {
                        Id = _snowflake.NextId(),
                        AcquisitionTime=DateTime.Now,
                        CellType = "",
                        CellBatch =_parameter.BatchNo,
                        TrayBarcode = _parameter.TrayBarcode,
                        TrayID = _parameter.TrayBarcodeID,
                        // TrayNo = index,
                        Barcode = bar,
                        RowNo = rowNo,
                        ColNo = (i + 1),
                        SeqNo = 241 + i - ((rowNo - 1) * 16),
                        CCDResult = strCCD[i * 6] == 1 ? "OK" : "NG",
                        CodeLong = (strCCD[i * 6 + 1] / 1000.000).ToString(),
                        CodeWidth = (strCCD[i * 6 + 2] / 1000.000).ToString(),
                        CodeHead = (strCCD[i * 6 + 3] / 1000.000).ToString(),
                        CodeTail = (strCCD[i * 6 + 4] / 1000.000).ToString(),
                        CodeTilt = (strCCD[i * 6 + 5] / 1000.000).ToString(),
                        ProductDate = datetime,
                        Status = 0
                    };

                    //var id = DB.Insert(plate);
                    var id = plate.Insert();
                    if (id != 0)
                    {
                        plateList1.Add(plate);
                        // deleteBatt.Add(batt);
                        removeBarcodes.Add(bar);
                    }

                    _homeStatic.AddBattery(plate, machineInfo_Type);
                    if (id <= 0) HaveNG = true;

                    RunLog($"【装盘】保存{(id > 0 ? "成功" : "失败")} 序号:{plate.SeqNo} 托盘{plate.TrayBarcode} 行号:{plate.RowNo} 列号:{plate.ColNo} 条码:{plate.Barcode}");
                }

                //data.PlateList.AddRange(plateList1);
                //// data.PlateQueueList.RemoveRange(deleteBatt);
                //data.PlateQueueList.RemoveRange(data.PlateQueueList.Where(x => removeBarcodes.Contains(x.Barcode)).ToList());

                if (HaveNG)
                {
                    var msg = $"【装盘】存储装盘数据失败 {_parameter.TrayBarcode}";
                    RunLog(msg, XingLucifer.IBase.Enums.MessageLevelType.错误);
                    //MyGrowl.WarningGlobal(msg);
                    //Task.Run(() => {
                    //    //MyGrowl.MessageBox($"{msg} {DateTime.Now}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    //});
                }
            }
            catch (Exception ex)
            {
                RunLog("【装盘】发生异常:{ex}", XingLucifer.IBase.Enums.MessageLevelType.错误);
                //MyGrowl.WarningGlobal($"【装盘】发生异常:{ex.Message}");
            }
            finally
            {
                var r1 = InjMachine.Write<short>("DM1205", new short[] { testResult });
                var r2 = InjMachine.Write<short>("DM1003", new short[] { 0 });
                RunLog($"【装盘】写结果信号  {testResult} {r1}.{r2} {(r1 && r2 ? "成功" : "失败")}");
            }
            return base.Handle();
        }

        #region 生成唯一虚拟条码

        // 喷码机的虚拟编码麻烦改成：26：L3 + 年月日时分 + 5位随机流水码 ；18：L4 + 年月日时分 + 5位随机流水码
        //例
        // 26：L3230815082812345
        // 18：L4230815082812345

        List<string> barcodeList = new List<string>(); // 存储生成的条码列表，每分钟清空一次
        DateTime lastGeneratedTime = DateTime.MinValue; // 上次生成条码的时间

        Random random = new Random();

        // 生成一个虚拟条码
        string GenerateBarcode()
        {
            DateTime now = DateTime.Now;
            string formattedDate = now.ToString("yyMMddHHmm");
            string randomSerial = random.Next(0, 100000).ToString("D5");

            string barcode = "L4" + formattedDate + randomSerial;

            return barcode;
        }

        // 生成唯一的条码，如果在同一分钟内有重复则重新生成
        string GenerateUniqueBarcode()
        {
            string barcode = GenerateBarcode();

            if (lastGeneratedTime.Minute != DateTime.Now.Minute)
            {
                barcodeList.Clear(); // 清空列表，进入新的一分钟
                lastGeneratedTime = DateTime.Now; // 更新上次生成条码的时间
            }

            while (barcodeList.Contains(barcode))
            {
                barcode = GenerateBarcode(); // 如果有重复则重新生成
            }

            barcodeList.Add(barcode); // 将新生成的条码添加到列表
            return barcode;
        }
        #endregion
        public class PlateBattery
        {
            public UInt16 ID { get; set; }
            public string Barcode { get; set; }
        }
    }
}
